package exceptional;
/*
* 抛出异常
* 当某个方法抛出了异常时，如果当前方法没有捕获异常，异常就会被抛到上层调用方法，直到遇到某个try ... catch被捕获为止：
* */
public class ThrowException {
    public static void main(String[] args) {

        //1:当某个方法抛出了异常时，如果当前方法没有捕获异常，异常就会被抛到上层调用方法，直到遇到某个try ... catch被捕获为止：
//        try {
//            process1();
//        }catch (Exception e){
//            e.printStackTrace();
//        }

        //3:异常类型转换
//        try {
//            process5(null);
//        }catch (Exception e){
//            e.printStackTrace();
//        }

        //4:异常屏蔽
//        process7();
//        process8();

        //5:练习
        try {
            System.out.println("税收是: " + tax(-10,20));
        }catch (IllegalArgumentException e){
            e.printStackTrace();
        }finally {
            System.out.println("END");
        }
    }
    static void process1(){
        process2();
    }
    static void process2(){
        Integer.parseInt(null);// 会抛出NumberFormatException
    }

    //2:抛出异常
    //如何抛出异常?参考Integer.parseInt()方法，抛出异常分两步：
    //(1):创建某个Exception的实例；
    //(2):用throw语句抛出。
    void process3(String s){
        if (s == null){
            NullPointerException e = new NullPointerException();
            throw e;
        }
    }
    //实际上，绝大部分抛出异常的代码都会合并写成一行：
    void process4(String s){
        if (s == null){
            throw new NullPointerException();
        }
    }
    //3:如果一个方法捕获了某个异常后，又在catch子句中抛出新的异常，就相当于把抛出的异常类型“转换”了：
    static void process5(String s){
        try {
            process6(s);
        }catch (NullPointerException e){
            throw new IllegalArgumentException(e);//把异常转换了
        }
    }
    static void process6(String s){
        if (s == null){
            throw new NullPointerException();
        }
    }

    //4:异常屏蔽
    //如果在执行finally语句时抛出异常，那么，catch语句的异常还能否继续抛出？
    static void process7(){
        try {
            Integer.parseInt("abc");
        } catch (Exception e) {
            System.out.println("catched");
            throw new RuntimeException(e);
        } finally {
            System.out.println("finally");
            throw new IllegalArgumentException();
        }
    }

    //这说明finally抛出异常后，原来在catch中准备抛出的异常就“消失”了，因为只能抛出一个异常。没有被抛出的异常称为“被屏蔽”的异常（Suppressed Exception）。
    //
    //在极少数的情况下，我们需要获知所有的异常。如何保存所有的异常信息？方法是先用origin变量保存原始异常，然后调用Throwable.addSuppressed()，把原始异常添加进来，最后在finally抛出：
//    static void process8(){
//        Exception origin = null;
//        try {
//            System.out.println(Integer.parseInt("abc"));
//        } catch (Exception e) {
//            origin = e;
//            throw e;
//        } finally {
//            Exception e = new IllegalArgumentException();
//            if (origin != null) {
//                e.addSuppressed(origin);
//            }
//            throw e;
//        }
//    }

    //5:练习
    static double tax(int salary,double rate){
        //TODO:如果传入参数为负,则抛出IllegalArgumentException
        if (salary<0 || rate <0){
            throw new IllegalArgumentException();
        }
        return salary * rate;
    }
}
